﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Dexter.Domain.Model;
using Dexter.Logger.Contracts;
using Dexter.Services;
using Dexter.Web.Mvc.Controllers.Backoffice.Extensions;
using Dexter.Web.Mvc.Extensions;
using Dexter.Web.Mvc.Filters;
using Dexter.Web.Mvc.ViewModel.Backoffice.Binders;
using Dexter.Web.Mvc.ViewModel.Backoffice.ViewsData.PostController;
using Dexter.Web.Utils;

namespace Dexter.Web.Mvc.Controllers.Backoffice {
	[Authorize ( Roles = "Poster" )]
	[DexterCallFilter ( false )]
	public class PostController : BackOfficeControllerBase {
		readonly ICategoryService categoryService;
		readonly IPostService postService;

		/// <summary>
		/// Initializes a new instance of the <see cref="PostController"/> class.
		/// </summary>
		/// <param name="configurationService">The configuration service.</param>
		/// <param name="webUtils">The web utils.</param>
		/// <param name="logger">The logger.</param>
		/// <param name="urlBuilder">The URL builder.</param>
		/// <param name="contactService">The contact service.</param>
		/// <param name="categoryService">The category service.</param>
		/// <param name="postService">The post service.</param>
		public PostController ( IConfigurationService configurationService , IWebUtils webUtils , ILogger logger , IUrlBuilder urlBuilder , IContactService contactService , ICategoryService categoryService , IPostService postService ) : base ( configurationService , webUtils , logger , urlBuilder , contactService ) {
			this.categoryService = categoryService;
			this.postService = postService;
		}

		[AcceptVerbs ( HttpVerbs.Get )]
		public ActionResult Index ( int? page , string username ) {
			int pageIndex = page ?? 1;

			pageIndex--;

			var data = base.GetViewData ( new PostListViewData ( base.WebUtils, base.Configuration, base.UrlBuilder ) );

			data.Posts = postService.GetCompleteListOfPostDtos ( pageIndex , 20 );

			return View ( data );
		}

		[AcceptVerbs ( HttpVerbs.Get )]
		public ActionResult Editor ( int? id ) {
			var data = base.GetViewData ( new PostEditorViewData ( base.WebUtils, base.Configuration, base.UrlBuilder ) );

			data.Categories = categoryService.GetCategoriesDtoStructure ( );
			
			data.Post = id.HasValue
			            	? postService.GetPostDtoByKey ( id.Value ).ToPostBinder ( )
			            	: PostBinder.EmptyInstance ( );

			return View ( data );
		}

		[ValidateAntiForgeryToken]
		[AcceptVerbs ( HttpVerbs.Post )]
		public ActionResult Editor ( PostBinder post ) {
			
			if ( !ModelState.IsValid ) {
				var data = base.GetViewData ( new PostEditorViewData ( base.WebUtils, base.Configuration, base.UrlBuilder ) );
				data.Categories = categoryService.GetCategoriesDtoStructure ( );
				data.Post = post;

				return View ( data );
			}

			Post item;

			IList<Category> postCategories = post.Categories.Where ( x => !string.IsNullOrEmpty(x.Name) ).Select ( category => categoryService.GetCategoryByKeyWithChilds ( category.Id ) ).ToList ( );

			if (!postCategories.Any ( )) {
				postCategories.Add ( categoryService.GetDefaultCategoryWithChilds ( ) );
			}

			if ( post.Id > 0 ) {
				item = postService.GetByKey ( post.Id );

				post.ToPost ( item );

				item.Username = HttpContext.User.Identity.Name;

				item.Categories.Clear (  );
				item.Categories.AddRange ( postCategories );

				if (item.PublishDate <= ConfigurationService.Configuration.GetFromUtcToUserTimeZone ( DateTime.Now.ToUniversalTime ( ) )) {
					item.Publish ( );
				}
				else {
					item.UnPublish ( );
				}

				postService.Update ( item );
			} else {
				item = Post.CreateNewPost ( post.Title , postCategories[ 0 ] , post.FormattedBody , HttpContext.User.Identity.Name );

				post.ToPost ( item );

				item.Username = HttpContext.User.Identity.Name;

				if (item.PublishDate <= ConfigurationService.Configuration.GetFromUtcToUserTimeZone ( DateTime.Now.ToUniversalTime ( ) )) {
					item.Publish ( );
				}
				else {
					item.UnPublish ( );
				}

				postService.Save ( item );
			}

			return this.ReturnFeedback ( MessageType.Positive, "PostSaved", base.UrlBuilder.BackOffice.PostList );
		}

		[AcceptVerbs ( HttpVerbs.Get )]
		public ActionResult ConfirmDelete ( int id ) {
			if(id <1)
				return HttpNotFound ( );

			var data = base.GetViewData ( new PostDeleteViewData ( base.WebUtils, base.Configuration, base.UrlBuilder ) );
			data.Post = postService.GetByKey ( id );

			return View ( data );
		}

		[AcceptVerbs ( HttpVerbs.Post )]
		[ValidateAntiForgeryToken]
		public ActionResult Delete ( int id ) {
			postService.Delete ( id );

			return this.ReturnFeedback ( MessageType.Positive, "PostDeleted", base.UrlBuilder.BackOffice.PostList );
		}
	}
}